﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using InfoJetSoft.Service.Entity;
using InfoJetSoft.Service.Util;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Administration;
using System.Runtime.InteropServices;
using Microsoft.SharePoint.WebControls;
using System.Net.Mail;
using System.Globalization;
using Microsoft.SharePoint.Administration.Claims;

namespace InfoJetSoft.Service.Worker
{
    //added by lishuchao
    class PNGUpdatePrincipalsWorker
    {
        private static bool[] AccountSelection = new bool[4];
        public static void updatePrincipals(Form form)
        {
            string contextId = form.ParamTable["xdoc_param_png_context_id"] as string;
            string pngId = form.ParamTable["xdoc_param_png_id"] as string;
            XmlElement contextElement = DOMUtil.findNodeByJetId(form, contextId) as XmlElement;
            if (contextElement != null)
            {
                string xml = form.ParamTable["xdoc_param_png_updated_xml"] as string;
                XmlDocument principalsDoc = new XmlDocument();
                principalsDoc.LoadXml(xml);

                //CID 0733 //2010.12.18 //Begin
                PNGInfo pngInfo = form.Manifest.PNGInfoTable[pngId] as PNGInfo;
                if (pngInfo.AllowMultiple.Equals("false"))
                {
                    contextElement.InnerXml = "";
                }
                //CID 0733 //2010.12.18 //End

                //CID 0914 //2011.05.20 //Begin
                string accountIdFilter = NamespaceUtil.toFullName(pngInfo.Prefix, "Person") + "/" + NamespaceUtil.toFullName(pngInfo.Prefix, "AccountId");
                //CID 0914 //2011.05.20 //End
                ArrayList accoundIdList = new ArrayList();
                XmlNodeList accountIdElementList = DOMUtil.selectNodes(contextElement, accountIdFilter, 0, form.XmlNsResolver);

                XmlNodeList principalElementList = principalsDoc.SelectNodes("/Principals/Principal");
                ArrayList accountNameList = new ArrayList();
                
                Guid siteID = SPContext.Current.Site.ID;
                Guid webID = SPContext.Current.Web.ID;
                IList<SPPrincipalInfo> prins = new List<SPPrincipalInfo>();
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    using (SPSite site = new SPSite(siteID))
                    {
                        using (SPWeb web = site.OpenWeb(webID))
                        {
                            ArrayList prinInnerTextList = new ArrayList();
                            ArrayList resolvedEntityList = new ArrayList();
                            foreach (XmlElement principalElement in principalElementList)
                            {
                                string prinInnerText = principalElement.InnerText;
                                if (string.IsNullOrEmpty(prinInnerText) || prinInnerTextList.Contains(prinInnerText))
                                    continue;
                                prinInnerTextList.Add(prinInnerText);

                                bool found = false;
                                string displayName = "";
                                string accountName = "";
                                string principalType = "";
                                string key = "";

                                prins = CustomResolveEntity(prinInnerText, web);
                                if (prins.Count == 1)
                                {
                                    SPPrincipalInfo prin = ((SPPrincipalInfo)prins[0]);
                                    if (null != prin)
                                    {
                                        displayName = prin.DisplayName;
                                        accountName = prin.LoginName;
                                        principalType = prin.PrincipalType.ToString();
                                        key = prin.PrincipalId.ToString();
                                        found = true;

                                        if (resolvedEntityList.Contains(accountName))
                                            continue;
                                        resolvedEntityList.Add(accountName);
                                    }
                                }
                                else if (prins.Count > 1)
                                {
                                    foreach (SPPrincipalInfo prin in prins)
                                    {
                                        if (accountNameList.Contains(prin.LoginName))
                                            continue;
                                        accountNameList.Add(prin.LoginName);
                                        accountName += (prin.LoginName + ";");
                                    }
                                }
                                foreach (XmlElement accountIdElement in accountIdElementList)
                                {
                                    string accountId = accountIdElement.InnerText.Trim();
                                    if (accountId.Length <= 0)
                                    {
                                        try
                                        {
                                            contextElement.RemoveChild(accountIdElement.ParentNode);
                                        }
                                        catch (Exception ex)
                                        {
                                        }
                                    }
                                    else
                                    {
                                        if (!accountNameList.Contains(accountId))
                                        {
                                            try
                                            {
                                                contextElement.RemoveChild(accountIdElement.ParentNode);
                                            }
                                            catch (Exception ex)
                                            {
                                            }
                                        }
                                        else
                                        {
                                            accoundIdList.Add(accountId);
                                        }
                                    }
                                }
                                if (found)
                                {
                                    //CID 0914 //2011.05.20 //Begin
                                    string nsPrefix = pngInfo.Prefix;
                                    string nsUri = "http://schemas.microsoft.com/office/infopath/2007/PartnerControls";
                                    if (form.Manifest.SolutionFormatVersion.StartsWith("2.0"))
                                    {
                                        nsUri = form.XmlNsResolver.GetURI(nsPrefix);
                                    }
                                    XmlElement personElement = form.XmlDoc.CreateElement(nsPrefix, "Person", nsUri);
                                    contextElement.AppendChild(personElement);
                                    XmlElement displayNameElement = form.XmlDoc.CreateElement(nsPrefix, "DisplayName", nsUri);
                                    displayNameElement.InnerText = displayName;
                                    personElement.AppendChild(displayNameElement);
                                    XmlElement accountIdElement = form.XmlDoc.CreateElement(nsPrefix, "AccountId", nsUri);
                                    accountIdElement.InnerText = accountName;
                                    personElement.AppendChild(accountIdElement);
                                    //XmlElement keyElement = form.XmlDoc.CreateElement(nsPrefix, "Key", nsUri);
                                    //keyElement.InnerText = key;
                                    //personElement.AppendChild(keyElement);
                                    XmlElement accountTypeElement = form.XmlDoc.CreateElement(nsPrefix, "AccountType", nsUri);
                                    accountTypeElement.InnerText = principalType;//DOMUtil.getNodeValue(principalElement.SelectSingleNode("PrincipalType"));
                                    personElement.AppendChild(accountTypeElement);
                                    //XmlElement isResolvedElement = form.XmlDoc.CreateElement(nsPrefix, "IsResolved", nsUri);
                                    //isResolvedElement.InnerText = "True";
                                    //personElement.AppendChild(isResolvedElement);
                                    //XmlElement classElement = form.XmlDoc.CreateElement(nsPrefix, "ResolvedClass", nsUri);
                                    //classElement.InnerText = "ms-entity-resolved";
                                    //personElement.AppendChild(classElement);
                                    //CID 0914 //2011.05.20 //End

                                    //CID 0828 //2011.03.10 //Begin
                                    if (form.FocusItemIndex == -1)
                                    {
                                        form.FocusItemIndex = DOMUtil.getChildElementIndex(contextElement, personElement);
                                    }
                                    //CID 0828 //2011.03.10 //End
                                }
                                else
                                {
                                    string nsPrefix = pngInfo.Prefix;
                                    string nsUri = "http://schemas.microsoft.com/office/infopath/2007/PartnerControls";
                                    if (form.Manifest.SolutionFormatVersion.StartsWith("2.0"))
                                    {
                                        nsUri = form.XmlNsResolver.GetURI(nsPrefix);
                                    }
                                    XmlElement personElement = form.XmlDoc.CreateElement(nsPrefix, "Person", nsUri);
                                    contextElement.AppendChild(personElement);
                                    XmlElement displayNameElement = form.XmlDoc.CreateElement(nsPrefix, "DisplayName", nsUri);
                                    displayNameElement.InnerText = prinInnerText;
                                    personElement.AppendChild(displayNameElement);
                                    XmlElement accountIdElement = form.XmlDoc.CreateElement(nsPrefix, "AccountId", nsUri);
                                    accountIdElement.InnerText = "Multiple entries matched, please click to resolve.";
                                    personElement.AppendChild(accountIdElement);
                                    XmlElement keyElement = form.XmlDoc.CreateElement(nsPrefix, "Key", nsUri);
                                    keyElement.InnerText = accountName;
                                    personElement.AppendChild(keyElement);
                                    XmlElement accountTypeElement = form.XmlDoc.CreateElement(nsPrefix, "AccountType", nsUri);
                                    accountTypeElement.InnerText = principalType;//DOMUtil.getNodeValue(principalElement.SelectSingleNode("PrincipalType"));
                                    personElement.AppendChild(accountTypeElement);
                                    XmlElement isResolvedElement = form.XmlDoc.CreateElement(nsPrefix, "IsResolved", nsUri);
                                    isResolvedElement.InnerText = "False";
                                    personElement.AppendChild(isResolvedElement);
                                    XmlElement classElement = form.XmlDoc.CreateElement(nsPrefix, "ResolvedClass", nsUri);
                                    classElement.InnerText = "ms-entity-unresolved";
                                    personElement.AppendChild(classElement);
                                    //CID 0914 //2011.05.20 //End

                                    //CID 0828 //2011.03.10 //Begin
                                    if (form.FocusItemIndex == -1)
                                    {
                                        form.FocusItemIndex = DOMUtil.getChildElementIndex(contextElement, personElement);
                                    }
                                }
                            }
                        }
                    }
                });
            }
        }

        private static IList<SPPrincipalInfo> CustomResolveEntity(string prinText, SPWeb web)
        {
            web.AllowUnsafeUpdates = true;
            IList<SPPrincipalInfo> list;

            SPPrincipalInfo info = SPUtility.ResolvePrincipal(web, prinText, SPPrincipalType.All, SPPrincipalSource.All, null, false);
            if (info != null)
            {
                list = new List<SPPrincipalInfo>();
                list.Add(info);
                return list;
            }
            int maxCount = 10;
            bool reachMaxCount = false;

            //list = SPUtility.SearchPrincipals(web.Site.WebApplication, null, prinText, SPPrincipalType.All, SPPrincipalSource.All, maxCount, out reachMaxCount);
            list = SPUtility.SearchPrincipals(web, prinText, SPPrincipalType.All, SPPrincipalSource.All, null, maxCount, out reachMaxCount);
            //list = SPUtility.SearchWindowsPrincipals(web.Site.WebApplication, prinText, SPPrincipalType.All, maxCount, out reachMaxCount);
            return list;
        }

        internal static void SetAccountSelection(string SelectionSet, ref bool[] AccountSelection)
        {
            if (SelectionSet != null)
            {
                string[] strArray = SelectionSet.Split(',');
                for (int i = strArray.GetLowerBound(0); i <= strArray.GetUpperBound(0); i++)
                {
                    try
                    {
                        AccountSelection[(int)((Microsoft.SharePoint.WebControls.PeopleEditor.AccountType)Enum.Parse(typeof(Microsoft.SharePoint.WebControls.PeopleEditor.AccountType), strArray[i], true))] = true;
                    }
                    catch
                    {
                    }
                }
            }
        }

        internal static SPPrincipalType ConvertAccountSelectionToPrincipalTypes(bool[] accountSelection)
        {
            SPPrincipalType none = SPPrincipalType.None;
            if (accountSelection[0])
            {
                none |= SPPrincipalType.User;
            }
            if (accountSelection[1])
            {
                none |= SPPrincipalType.DistributionList;
            }
            if (accountSelection[2])
            {
                none |= SPPrincipalType.SecurityGroup;
            }
            if (accountSelection[3])
            {
                none |= SPPrincipalType.SharePointGroup;
            }
            return none;
        }
    }
}
